package com.linglan.bff.controller.app;

import cn.dev33.satoken.annotation.SaIgnore;
import com.linglan.bff.vo.app.doctor.DoctorDetailVO;
import com.linglan.bff.vo.app.doctor.DoctorListVO;
import com.linglan.bff.vo.app.doctor.HotDoctorListVO;
import com.linglan.common.api.Page;
import com.linglan.common.api.Query;
import com.linglan.common.api.R;
import com.linglan.common.enums.HotSearchType;
import com.linglan.common.utils.PageUtil;
import com.linglan.modules.department.dto.result.DepartmentResult;
import com.linglan.modules.department.service.BizDepartmentService;
import com.linglan.modules.doctor.dto.result.DoctorResult;
import com.linglan.modules.doctor.dto.result.HotSearchResult;
import com.linglan.modules.doctor.service.BizDoctorService;
import com.linglan.modules.doctor.service.BizHosearchService;
import com.linglan.modules.hospital.dto.result.HospitalResult;
import com.linglan.modules.hospital.service.BizHospitalService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 医生相关业务模块
 */
@RestController
@RequestMapping("/app/doctors")
@Slf4j
public class DoctorController {
    @Resource
    private BizDoctorService doctorService;
    @Resource
    private BizDepartmentService departmentService;
    @Resource
    private BizHospitalService hospitalService;
    @Resource
    private BizHosearchService hotSearchService;

    /**
     * 分页查询医生列表
     *
     * @param query
     * @return
     */
    @GetMapping("/page")
    @SaIgnore
    public R<Page<DoctorListVO>> findByPage(Query query) {
        Page<DoctorResult> resultPage = doctorService.findByPage(query, null);
        Page<DoctorListVO> voPage = PageUtil.copyPurePage(resultPage);
        List<DoctorResult> records = resultPage.getRecords();
        List<DoctorListVO> voList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(records)) {
            List<Long> departmentIds = records.stream().map(DoctorResult::getDepartmentId).collect(Collectors.toList());
            Map<Long, DepartmentResult> departmentResultMap = departmentService.findGroupById(departmentIds);
            for (DoctorResult record : records) {
                DoctorListVO vo = new DoctorListVO();
                vo.setId(record.getId().toString());
                Long departmentId = record.getDepartmentId();
                vo.setDepartmentId(departmentId.toString());
                DepartmentResult departmentResult = departmentResultMap.get(departmentId);
                if (departmentResult != null) {
                    vo.setDepartmentName(departmentResult.getName());
                }
                vo.setName(record.getName());
                vo.setAvatar(record.getAvatar());
                vo.setTitle(record.getTitle());
                vo.setTags(record.getTags());
                vo.setCzTime(record.getCzTime());
                vo.setTreatCount(record.getTreatCount());
                voList.add(vo);
            }
        }
        voPage.setRecords(voList);
        return R.ok(voPage);
    }

    /**
     * 查询医生详情
     *
     * @param doctorId
     * @return
     */
    @GetMapping("/{doctorId}/detail")
    @SaIgnore
    public R<DoctorDetailVO> findDetailById(@PathVariable Long doctorId) {
        DoctorResult doctorResult = doctorService.findById(doctorId);
        if (doctorResult == null) {
            log.error("医生不存在 doctorId={}", doctorId);
            return R.failed("医生不存在");
        }
        Map<Long, DepartmentResult> departmentResultMap = departmentService.findGroupById(Collections.singletonList(doctorResult.getDepartmentId()));

        Long hospitalId = doctorResult.getHospitalId();
        HospitalResult hospitalResult = hospitalService.findById(hospitalId);
        DoctorDetailVO vo = new DoctorDetailVO();
        vo.setId(doctorResult.getId().toString());
        Long departmentId = doctorResult.getDepartmentId();
        vo.setDepartmentId(departmentId.toString());
        DepartmentResult departmentResult = departmentResultMap.get(departmentId);
        if (departmentResult != null) {
            vo.setDepartmentName(departmentResult.getName());
        }
        vo.setName(doctorResult.getName());
        vo.setAvatar(doctorResult.getAvatarDetail());
        vo.setTitle(doctorResult.getTitle());
        vo.setTags(doctorResult.getTags());
        vo.setCzTime(doctorResult.getCzTime());
        vo.setScore(doctorResult.getScore().stripTrailingZeros().toPlainString());
        vo.setTreatCount(doctorResult.getTreatCount());
        vo.setStrength(doctorResult.getStrength());
        vo.setHospitalName(hospitalResult.getName());
        vo.setHospitalAddress(hospitalResult.getAddress());
        vo.setHospitalLat(hospitalResult.getLat().toString());
        vo.setHospitalLng(hospitalResult.getLng().toString());
        return R.ok(vo);
    }

    /**
     * 根据科室id分页查询医生列表
     *
     * @param departmentId
     * @param query
     * @return
     */
    @GetMapping("/{departmentId}/page")
    @SaIgnore
    public R<Page<DoctorListVO>> findByPage(@PathVariable Long departmentId, Query query) {
        Page<DoctorResult> resultPage = doctorService.findByPage(query, departmentId);
        Page<DoctorListVO> voPage = PageUtil.copyPurePage(resultPage);
        List<DoctorResult> records = resultPage.getRecords();
        List<DoctorListVO> voList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(records)) {
            List<Long> departmentIds = records.stream().map(DoctorResult::getDepartmentId).collect(Collectors.toList());
            Map<Long, DepartmentResult> departmentResultMap = departmentService.findGroupById(departmentIds);
            for (DoctorResult record : records) {
                DoctorListVO vo = new DoctorListVO();
                vo.setId(record.getId().toString());
                Long departmentIdCur = record.getDepartmentId();
                vo.setDepartmentId(departmentIdCur.toString());
                DepartmentResult departmentResult = departmentResultMap.get(departmentIdCur);
                if (departmentResult != null) {
                    vo.setDepartmentName(departmentResult.getName());
                }
                vo.setName(record.getName());
                vo.setAvatar(record.getAvatar());
                vo.setTitle(record.getTitle());
                vo.setTags(record.getTags());
                vo.setCzTime(record.getCzTime());
                vo.setTreatCount(record.getTreatCount());
                voList.add(vo);
            }
        }
        voPage.setRecords(voList);
        return R.ok(voPage);
    }

    /**
     * 搜索医生
     *
     * @param query
     * @param keyword
     * @return
     */
    @GetMapping("/search")
    @SaIgnore
    public R<Page<DoctorListVO>> findByPage(Query query, @RequestParam(required = false) String keyword) {
        Page<DoctorResult> resultPage = doctorService.searchByPage(query, keyword);
        Page<DoctorListVO> voPage = PageUtil.copyPurePage(resultPage);
        List<DoctorResult> records = resultPage.getRecords();
        List<DoctorListVO> voList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(records)) {
            List<Long> departmentIds = records.stream().map(DoctorResult::getDepartmentId).collect(Collectors.toList());
            Map<Long, DepartmentResult> departmentResultMap = departmentService.findGroupById(departmentIds);
            for (DoctorResult record : records) {
                DoctorListVO vo = new DoctorListVO();
                vo.setId(record.getId().toString());
                Long departmentId = record.getDepartmentId();
                vo.setDepartmentId(departmentId.toString());
                DepartmentResult departmentResult = departmentResultMap.get(departmentId);
                if (departmentResult != null) {
                    vo.setDepartmentName(departmentResult.getName());
                }
                vo.setName(record.getName());
                vo.setAvatar(record.getAvatar());
                vo.setTitle(record.getTitle());
                vo.setTags(record.getTags());
                vo.setCzTime(record.getCzTime());
                vo.setTreatCount(record.getTreatCount());
                voList.add(vo);
            }
        }
        voPage.setRecords(voList);
        return R.ok(voPage);
    }

    /**
     * 热门搜索
     *
     * @return
     */
    @GetMapping("/search/hot")
    @SaIgnore
    public R<List<HotDoctorListVO>> findHotSearch() {

        List<HotSearchResult> hotSearch = hotSearchService.findHotSearch();

        List<HotDoctorListVO> voList = new ArrayList<>();
        if (CollectionUtils.isEmpty(hotSearch)) {
            return R.ok(voList);
        }
        //对hotSearch的数据按type进行分类，分类后把objId合并到list中
        Map<HotSearchType, List<Long>> hotSearchMap = hotSearch.stream().collect(Collectors.groupingBy(HotSearchResult::getType, Collectors.mapping(HotSearchResult::getObjId, Collectors.toList())));
        Set<Map.Entry<HotSearchType, List<Long>>> entries = hotSearchMap.entrySet();
        Map<Long, DoctorResult> doctorMap = new HashMap<>();
        for (Map.Entry<HotSearchType, List<Long>> entry : entries) {
            HotSearchType key = entry.getKey();
            if (key == HotSearchType.DOC) {
                doctorMap = doctorService.findByIds(entry.getValue()).stream().collect(Collectors.toMap(DoctorResult::getId, Function.identity(), (o, n)->n));
            }
        }

        for (HotSearchResult search : hotSearch) {
            HotSearchType type = search.getType();
            if (type == HotSearchType.DOC) {
                DoctorResult doctorResult = doctorMap.get(search.getObjId());
                HotDoctorListVO vo = new HotDoctorListVO();
                vo.setId(search.getId().toString());
                vo.setName(doctorResult.getName());
                vo.setType(type);
                voList.add(vo);
            }
        }
        return R.ok(voList);
    }


}
